package com.shengqin.service.impl;

import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shengqin.common.pojo.CommonPage;
import com.shengqin.config.CommonException;
import com.shengqin.entity.*;
import com.shengqin.mapper.ReservationMapper;
import com.shengqin.service.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements IReservationService {

    @Resource
    private IPlanService planService;
    @Resource
    private IStudentService studentService;
    @Resource
    private ISchoolService schoolService;
    @Resource
    private IPlanStudentService planStudentService;
    @Resource
    private IPlanRelationClassesService planRelationClassesService;
    @Resource
    private IPlanReservationItemService planReservationItemService;
    @Resource
    private IFreeTestApplyService freeTestApplyService;

    @Override
    public Boolean apply(Reservation reservation) {
        Plan plan = planService.getById(reservation.getPlanId());
        if (plan == null) {
            throw new CommonException("该计划不存在，请确认后再试！");
        }
        if (!plan.getOpenReservation()) {
            throw new CommonException("该计划未开放预约功能，暂时无法预约！");
        }
        PlanStudent planStudent = planStudentService.queryByPlanIdAndStudyCode(reservation.getStudyCode(), reservation.getPlanId());
        if (planStudent == null) {
            throw new CommonException("未查询到您的信息，请联系管理员！");
        }

        long count = queryReservationCount(reservation.getReservationId());
        PlanReservationItem reservationItem = planReservationItemService.getById(reservation.getReservationId());
        if (reservationItem.getMaxNum() != null && count >= reservationItem.getMaxNum()) {
            throw new CommonException("预约人数已满，无法预约！");
        }

        Reservation queryReservation = getByStudyCodeAndReservationId(reservation.getStudyCode(), reservation.getReservationId());
        if (queryReservation != null) {
            throw new CommonException("您已预约" + queryReservation.getTestOfDay() + " " + queryReservation.getTestOfTime() + "，无法再次预约");
        }

        School school = schoolService.getById(planStudent.getSchoolId());
        reservation.setCardNo(planStudent.getCardNo());
        reservation.setIdCard(planStudent.getCardNo());
        reservation.setName(planStudent.getName());
        reservation.setSchoolName(school.getName());
        reservation.setPlanName(plan.getName());
        reservation.setCreateTime(LocalDateTime.now());
        return saveOrUpdate(reservation);
    }

    private long queryReservationCount(Long reservationId) {
        QueryWrapper<Reservation> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Reservation::getReservationId, reservationId);
        wrapper.lambda().eq(Reservation::getStatus, 1);
        return count(wrapper);
    }

    private Reservation getByStudyCodeAndReservationId(String studyCode, Long reservationId) {
        QueryWrapper<Reservation> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Reservation::getReservationId, reservationId);
        wrapper.lambda().eq(Reservation::getStudyCode, studyCode);
        wrapper.lambda().eq(Reservation::getStatus, 1);
        return getOne(wrapper);
    }

    @Override
    public Student login(Reservation reservation) {
        if (!StringUtils.hasLength(reservation.getStudyCode())) {
            throw new CommonException("请输入学籍号");
        }
        if (!StringUtils.hasLength(reservation.getLoginPassword())) {
            throw new CommonException("请输入登录密码");
        }
        Student student = studentService.getByStudyCode(reservation.getStudyCode());
        if (student == null) {
            throw new CommonException("未查询到学生信息，请确认后再试！");
        }
        String loginPassword = MD5.create().digestHex(reservation.getLoginPassword());
        if (!loginPassword.equals(student.getLoginPassword())) {
            throw new CommonException("登录密码错误,请重试!");
        }
        return student;
    }

    @Override
    public List<PlanReservationItem> queryPlanList(Reservation reservation) {
        QueryWrapper<PlanRelationClasses> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PlanRelationClasses::getShcoolId, reservation.getSchoolId());
        List<PlanRelationClasses> planRelationClassesList = planRelationClassesService.list(wrapper);

        if (CollectionUtils.isEmpty(planRelationClassesList)) {
            return new ArrayList<>();
        }

        List<Integer> planIds = planRelationClassesList.stream().map(PlanRelationClasses::getPlanId).distinct().collect(Collectors.toList());

        QueryWrapper<Plan> planWrapper = new QueryWrapper<>();
        planWrapper.lambda().eq(Plan::getOpenReservation, 1);
        planWrapper.lambda().in(Plan::getId, planIds);
        planWrapper.lambda().in(Plan::getState, "1", "2");
        planWrapper.lambda().orderByDesc(Plan::getId);
        List<Plan> planList = planService.list(planWrapper);

        QueryWrapper<PlanReservationItem> planReservationItemWrapper = new QueryWrapper<>();
        planReservationItemWrapper.lambda().in(PlanReservationItem::getPlanId, planList.stream().map(Plan::getId).collect(Collectors.toList()));
        planReservationItemWrapper.lambda().eq(PlanReservationItem::getEnabled, 1);
        planReservationItemWrapper.lambda().orderByDesc(PlanReservationItem::getId);

        List<PlanReservationItem> reservationItems = planReservationItemService.list(planReservationItemWrapper);
        return reservationItems;
    }

    @Override
    public Page<Reservation> getPage(CommonPage<Reservation> commonPage) {
        QueryWrapper<Reservation> wrapper = new QueryWrapper<>();
        if (commonPage.getQueryParam() != null) {
            Reservation reservation = commonPage.getQueryParam();
            if (StringUtils.hasLength(reservation.getStudyCode())) {
                wrapper.lambda().eq(Reservation::getStudyCode, reservation.getStudyCode());
            }
            if (StringUtils.hasLength(reservation.getName())) {
                wrapper.lambda().eq(Reservation::getName, reservation.getName());
            }
            if (reservation.getTestOfDay() != null) {
                wrapper.lambda().eq(Reservation::getTestOfDay, reservation.getTestOfDay());
            }
        }
        Page<Reservation> page = new Page<>(commonPage.getPageNo(), commonPage.getPageSize());
        page(page, wrapper);
        return page;
    }

    @Override
    public List<Reservation> queryMyReservationList(Reservation reservation) {
        QueryWrapper<Reservation> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Reservation::getStudyCode, reservation.getStudyCode());
        wrapper.lambda().orderByDesc(Reservation::getId);
        return list(wrapper);
    }

    @Override
    public Boolean cancelApply(Reservation reservation) {
        Reservation oldReservation = getById(reservation.getId());
        oldReservation.setStatus(2);
        return updateById(oldReservation);
    }

    @Override
    public Page<Reservation> queryPage(CommonPage<Reservation> reservationPagePram) {
        Reservation reservation = reservationPagePram.getQueryParam();
        QueryWrapper<Reservation> wrapper = new QueryWrapper<>();
        if (reservation != null) {
            if (reservation.getReservationId() != null) {
                wrapper.lambda().eq(Reservation::getReservationId, reservation.getReservationId());
            }
            if (reservation.getSchoolId() != null) {
                wrapper.lambda().eq(Reservation::getSchoolId, reservation.getSchoolId());
            }
            if (StringUtils.hasLength(reservation.getStudyCode())) {
                wrapper.lambda().eq(Reservation::getStudyCode, reservation.getStudyCode());
            }
            if (StringUtils.hasLength(reservation.getName())) {
                wrapper.lambda().like(Reservation::getName, reservation.getName());
            }
            if (StringUtils.hasLength(reservation.getSchoolName())) {
                wrapper.lambda().eq(Reservation::getSchoolName, reservation.getSchoolName());
            }
        }
        Page<Reservation> reservationPage = new Page<>(reservationPagePram.getPageNo(), reservationPagePram.getPageSize());
        return page(reservationPage, wrapper);
    }

    @Override
    public Boolean applyFreeTest(FreeTestApply freeTestApply) {
        if (freeTestApply.getId() == null) {
            Reservation queryReservation = getByStudyCodeAndReservationId(freeTestApply.getStudyCode(), Long.valueOf(freeTestApply.getReservationId()));
            if (queryReservation != null) {
                throw new CommonException("您已提交预约，无法再申请免测！");
            }
            freeTestApply.setCreateTime(LocalDateTime.now());
            if (StringUtils.hasLength(freeTestApply.getReservationId())) {
                FreeTestApply freeTestApplyData = freeTestApplyService.getByStudyCodAndReservationId(freeTestApply.getStudyCode(), Long.valueOf(freeTestApply.getReservationId()));
                if (freeTestApplyData != null) {
                    throw new CommonException("您已申请过，请不要重复提交！");
                }
                PlanReservationItem reservationItem = planReservationItemService.getById(freeTestApply.getReservationId());
                freeTestApply.setPlanId(reservationItem.getPlanId());
                PlanStudent planStudent = planStudentService.queryByPlanIdAndStudyCode(freeTestApply.getStudyCode(), reservationItem.getPlanId());
                if (planStudent == null) {
                    throw new CommonException("未查询到您的信息，请联系管理员！");
                }
                freeTestApply.setSex(planStudent.getSex());
                freeTestApply.setGradeId(planStudent.getGradeId().toString());
                freeTestApply.setState(1);
                freeTestApply.setName(planStudent.getName());
            }
        }
        return freeTestApplyService.saveOrUpdate(freeTestApply);
    }

    @Override
    public Boolean updatePassword(Student student) {
        if (student.getLoginPassword().equalsIgnoreCase("888888")) {
            throw new CommonException("密码不允许修改为默认密码");
        }
        Student std = studentService.getById(student.getId());
        std.setLoginPassword(MD5.create().digestHex(student.getLoginPassword()));
        std.setIsUpdatePwd(true);
        return studentService.updateById(std);
    }

    @Override
    public Boolean reviewFreeTest(FreeTestApply freeTestApply) {
        FreeTestApply testApply = freeTestApplyService.getById(freeTestApply.getId());
        testApply.setState(freeTestApply.getState());
        testApply.setRefundReason(freeTestApply.getRefundReason());
        return freeTestApplyService.updateById(testApply);
    }
}
